home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 4 / FM Towns Free Software Collection 4 - Disc 1.iso / msdos / cache / source / cache.c next >
Encoding:
C/C++ Source or Header  |  1991-10-19  |  11.6 KB  |  558 lines

  1. /**********************************************
  2.  
  3.     cache deiver Program
  4.  
  5.     1991.04.15    make by Ken
  6.  
  7.     compile use : cl /Zp /Ze
  8.  
  9. ***********************************************/
  10. #include    <stdio.h>
  11. #include    <dos.h>
  12. #include    "defs.h"
  13.  
  14. void        farmemcpy(char far *p,char far *s,int n);
  15. uchar        sum_calc(char far *p,ushort sz);
  16. void        Dev_str_call(char far *ent,REQ far *req);
  17. void        Dev_int_call(char far *ent);
  18. int        DOS_allocmem(int size,unsigned *seg);
  19. void        DOS_memfree(unsigned seg);
  20. DEVHED    far     *init_dmy_dev(void);
  21. DPB    far    *get_DPB(int dev);
  22. DPB    far    *link_DPB(void);
  23.  
  24. ushort        psp_seg;
  25. uchar        Cache_off=FALSE;
  26. uchar        hit_flg=0;
  27. uchar        max_dev=0;
  28. ushort        SecLen=0;
  29. uchar        SecAlc=0;
  30. ushort        DatSec=0;
  31. ushort        MaxCls=0;
  32. char    far    *tmp=NULL;
  33. DEVHED    far    *dmy_dev=NULL;
  34. REQ        dum_req;
  35.  
  36. DPB     far    *dpb_ptr[MAX_DEV];
  37. REQ     far    *req_ptr[MAX_DEV];
  38. DEVHED    far    *dev_ent[MAX_DEV];
  39.  
  40. SEC_PTR     *use_tbl[MAX_HASH];
  41. SEC_PTR     *lru_tbl[MAX_HASH];
  42. SEC_PTR        tbl_buf[MAX_SEC];
  43.  
  44. int    serch(uchar dev,ulong sec,int md)
  45. {
  46.     int     hs;
  47.     register SEC_PTR *bp;
  48.     register SEC_PTR *tp;
  49.  
  50.     hs = HASH(sec);
  51.  
  52.     hit_flg = FALSE;
  53.     tp = bp = lru_tbl[hs];
  54.     while ( bp != NULL ) {
  55.         if ( bp->dev == dev && bp->sec == sec ) {
  56.             hit_flg = TRUE;
  57.             break;
  58.         } else if ( bp->next == NULL )
  59.             break;
  60.         tp = bp;
  61.         bp = bp->next;
  62.     }
  63.     if ( tp != bp && (md != FALSE || hit_flg != FALSE) ) {
  64.         tp->next = bp->next;
  65.         bp->next = lru_tbl[hs];
  66.         lru_tbl[hs] = bp;
  67.     }
  68.     return (bp == NULL ? 0:((uint)(bp) - (uint)(tbl_buf)) / sizeof(SEC_PTR));
  69. }
  70. void    use_set(int pos)
  71. {
  72.     int     hs;
  73.     SEC_PTR *pp;
  74.     register SEC_PTR *bp;
  75.     register SEC_PTR *tp;
  76.  
  77.     if ( pos >= MAX_SEC )
  78.     return;
  79.  
  80.     pp = &(tbl_buf[pos]);
  81.  
  82.     if ( bp->dev == USE_DEV )
  83.         return;
  84.  
  85.     hs = HASH(pp->sec);
  86.     tp = bp = lru_tbl[hs];
  87.     while ( bp != NULL ) {
  88.         if ( bp == pp )
  89.             break;
  90.         tp = bp;
  91.         bp = bp->next;
  92.     }
  93.  
  94.     if ( bp == NULL )
  95.         return;
  96.  
  97.     if ( tp != bp )
  98.         tp->next = bp->next;
  99.     else
  100.         lru_tbl[hs] = bp->next;
  101.  
  102.     bp->dev = USE_DEV;
  103.     bp->next = use_tbl[hs];
  104.     use_tbl[hs] = bp;
  105. }
  106. void    lru_set(int pos)
  107. {
  108.     int     hs;
  109.     SEC_PTR *pp;
  110.     register SEC_PTR *bp;
  111.     register SEC_PTR *tp;
  112.  
  113.     if ( pos >= MAX_SEC )
  114.     return;
  115.  
  116.     pp = &(tbl_buf[pos]);
  117.  
  118.     if ( pp->dev != USE_DEV )
  119.         return;
  120.  
  121.     hs = HASH(pp->sec);
  122.     tp = bp = use_tbl[hs];
  123.     while ( bp != NULL ) {
  124.         if ( bp == pp )
  125.             break;
  126.         tp = bp;
  127.         bp = bp->next;
  128.     }
  129.  
  130.     if ( bp == NULL )
  131.         return;
  132.  
  133.     if ( tp != bp )
  134.         tp->next = bp->next;
  135.     else
  136.         use_tbl[hs] = bp->next;
  137.  
  138.     bp->dev = FRE_DEV;
  139.     bp->next = lru_tbl[hs];
  140.     lru_tbl[hs] = bp;
  141. }
  142. void    flush_tbl(int max_sec)
  143. {
  144.     int     i,hs;
  145.     register SEC_PTR *bp;
  146.  
  147.     for ( i = 0 ; i < MAX_HASH ; i++ )
  148.     use_tbl[i] = lru_tbl[i] = NULL;
  149.  
  150.     bp = tbl_buf;
  151.     for ( i = 0 ; i < max_sec && i < MAX_SEC ; i++ ) {
  152.     hs = HASH(i);
  153.     bp->sec = i;
  154.     bp->dev = USE_DEV;
  155.     bp->next = use_tbl[hs];
  156.     use_tbl[hs] = bp;
  157.     bp++;
  158.     }
  159. }
  160. void    flush_dev(uchar dev)
  161. {
  162.     int     i;
  163.     register SEC_PTR *bp;
  164.  
  165.     for ( i = 0 ; i < MAX_HASH ; i++ ) {
  166.     bp = lru_tbl[i];
  167.     while ( bp != NULL ) {
  168.         if ( bp->dev == dev )
  169.         bp->dev = FRE_DEV;
  170.         bp = bp->next;
  171.     }
  172.     }
  173. }
  174. void    Device_call(uchar dev,REQ far *req)
  175. {
  176.     union {
  177.     char far *p;
  178.     short    s[2];
  179.     } pp;
  180.  
  181.     pp.p = (char far *)(dev_ent[dev]);
  182.  
  183.     pp.s[0] = dev_ent[dev]->str_ent;
  184.     Dev_str_call(pp.p,req);
  185.  
  186.     pp.s[0] = dev_ent[dev]->int_ent;
  187.     Dev_int_call(pp.p);
  188. }
  189. int    Read_sub(ushort sec,char far *buf)
  190. {
  191.     dum_req.len = 19;
  192.     dum_req.unit = dpb_ptr[0]->UnitNum;
  193.     dum_req.cmds = 4;
  194.     dum_req.stat = 0;
  195.     dum_req.md_id = dpb_ptr[0]->MedId;
  196.     dum_req.x.rdwt.buff = buf;
  197.     dum_req.x.rdwt.sect = sec;
  198.     dum_req.x.rdwt.count = 1;
  199.     Device_call(0,(REQ far *)&dum_req);
  200.     return ((dum_req.stat & 0x8000) != 0 ? ERR:FALSE);
  201. }
  202. int    Write_sub(ushort sec,char far *buf)
  203. {
  204.     dum_req.len = 19;
  205.     dum_req.unit = dpb_ptr[0]->UnitNum;
  206.     dum_req.cmds = 8;
  207.     dum_req.stat = 0;
  208.     dum_req.md_id = dpb_ptr[0]->MedId;
  209.     dum_req.x.rdwt.buff = buf;
  210.     dum_req.x.rdwt.sect = sec;
  211.     dum_req.x.rdwt.count = 1;
  212.     Device_call(0,(REQ far *)&dum_req);
  213.     return ((dum_req.stat & 0x8000) != 0 ? ERR:FALSE);
  214. }
  215. void    Cache_set(uchar dev,ushort sec,char far *buf)
  216. {
  217.     int     rt;
  218.     ushort  sz,pos;
  219.     ulong   lsec;
  220.  
  221.     sz = dpb_ptr[dev]->SecLen;
  222.     lsec = (ulong)sec * ((sz + SecLen -1) / SecLen);
  223.  
  224.     while ( (int)sz > 0 ) {
  225.         if ( (pos = serch(dev,lsec,TRUE)) == 0 )
  226.             break;
  227.  
  228.         if ( sz < SecLen ) {
  229.             farmemcpy(tmp,buf,sz);
  230.             rt = Write_sub(pos,tmp);
  231.         } else
  232.             rt = Write_sub(pos,buf);
  233.  
  234.     if ( rt != FALSE ) {
  235.         use_set(pos);
  236.         continue;
  237.     }
  238.  
  239.         tbl_buf[pos].dev = dev;
  240.         tbl_buf[pos].sec = lsec;
  241.         tbl_buf[pos].sum = sum_calc(buf,sz);
  242.  
  243.         buf += SecLen;
  244.         sz -= SecLen;
  245.         lsec++;
  246.     }
  247. }
  248. int    Cache_chk(uchar dev,ushort sec,char far *buf)
  249. {
  250.     int     rt;
  251.     ushort  sz,pos;
  252.     ulong   lsec;
  253.  
  254.     sz = dpb_ptr[dev]->SecLen;
  255.     lsec = (ulong)sec * ((sz + SecLen - 1) / SecLen);
  256.  
  257.     while ( (int)sz > 0 ) {
  258.         if ( (pos = serch(dev,lsec,FALSE)) == 0 || hit_flg == FALSE )
  259.         return FALSE;
  260.  
  261.         if ( sz < SecLen ) {
  262.             rt = Read_sub(pos,tmp);
  263.             farmemcpy(buf,tmp,sz);
  264.         } else
  265.             rt = Read_sub(pos,buf);
  266.  
  267.         if ( rt != FALSE || tbl_buf[pos].sum != sum_calc(buf,sz) ) {
  268.             use_set(pos);
  269.             continue;
  270.         }
  271.  
  272.         buf += SecLen;
  273.         sz -= SecLen;
  274.         lsec++;
  275.     }
  276.  
  277.     return TRUE;
  278. }
  279. void    cls_lru_set(ushort cls)
  280. {
  281.     int     i;
  282.     ushort  sec;
  283.  
  284.     if ( cls < 2 || cls >= MaxCls )
  285.         return;
  286.  
  287.     sec = (cls - 2) * SecAlc + DatSec;
  288.  
  289.     for ( i = 0 ; i < SecAlc ; i++ )
  290.         lru_set(sec++);
  291. }
  292. void    cls_use_set(ushort cls)
  293. {
  294.     int     i;
  295.     ushort  sec;
  296.  
  297.     if ( cls < 2 || cls >= MaxCls )
  298.         return;
  299.  
  300.     sec = (cls - 2) * SecAlc + DatSec;
  301.  
  302.     for ( i = 0 ; i < SecAlc ; i++ )
  303.         use_set(sec++);
  304. }
  305. void    FAT_chk(int no,char far *p)
  306. {
  307.     int     i,n,max;
  308.  
  309.     no *= SecLen;
  310.     n = (no + 2) / 3;
  311.     i = n * 3 - no;
  312.     max = SecLen - 3;
  313.  
  314.     while ( i < max ) {
  315.  
  316.         if ( (*((short far *)(&p[i])) & 0x0FFF) == 0 )
  317.             cls_lru_set(n * 2);
  318.         else
  319.             cls_use_set(n * 2);
  320.  
  321.         if ( (*((short far *)(&p[i+1])) & 0xFFF0) == 0 )
  322.             cls_lru_set(n * 2 + 1);
  323.         else
  324.             cls_use_set(n * 2 + 1);
  325.  
  326.         n++;
  327.         i += 3;
  328.     }
  329. }
  330. void    Device_entry(uchar dev)
  331. {
  332.     int     i;
  333.     DPB far *dp;
  334.     REQ far *rp;
  335.     BPB far *bp;
  336.     ushort  sec;
  337.     char far *buf;
  338.  
  339.     dp = dpb_ptr[dev];
  340.     rp = req_ptr[dev];
  341.  
  342.     if ( dev == 0 ) {        /* Cache Buffer Device */
  343.     switch(rp->cmds) {
  344.     case 2:        /* Build BPB */
  345.         Device_call(dev,rp);
  346.         bp = rp->x.build.bpb;
  347.  
  348.         if ( (rp->stat & 0x8000) != 0 || SecLen < bp->SecLen ) {
  349.         Cache_off = TRUE;
  350.         break;
  351.         }
  352.         
  353.         SecLen = bp->SecLen;
  354.         SecAlc = bp->SecAlc + 1;
  355.         DatSec = bp->ResSec + 
  356.              bp->DirEnt * 32 / bp->SecLen + 
  357.              bp->FatLen * bp->FatSec;
  358.         MaxCls = (bp->MaxSec - DatSec) / SecAlc;
  359.  
  360.         flush_tbl(bp->MaxSec);
  361.         Cache_off = FALSE;
  362.         break;
  363.  
  364.     case 4:        /* Read */
  365.     case 8:        /* Write */
  366.     case 9:        /* Write & Verify */
  367.         Device_call(dev,rp);
  368.         if ( (rp->stat & 0x8000) != 0 )
  369.         break;
  370.  
  371.         sec = rp->x.rdwt.sect;
  372.         buf = rp->x.rdwt.buff;
  373.         i = rp->x.rdwt.count;
  374.  
  375.         while ( i-- > 0 ) {
  376.         if ( sec >= dp->ResSec && (sec - dp->ResSec) < dp->FatSec )
  377.             FAT_chk(sec - dp->ResSec,buf);
  378.         else
  379.             use_set(sec);
  380.         sec++;
  381.         buf += dp->SecLen;
  382.         }
  383.         break;
  384.  
  385.     case 80:    /* Ext Command Get Mode */
  386.         rp->x.ext.mode = Cache_off;
  387.         rp->x.ext.max_dev = max_dev;
  388.         rp->x.ext.dpb_ptr = (DPB far *)dpb_ptr;
  389.         rp->x.ext.lru_tbl = (SEC_PTR far *)lru_tbl;
  390.         rp->x.ext.use_tbl = (SEC_PTR far *)use_tbl;
  391.         rp->stat = 0x0100;
  392.         break;
  393.  
  394.     case 81:    /* Ext Command Exit Cache */
  395.         for ( i = 0 ; i < max_dev ; i++ )
  396.         dpb_ptr[i]->DevEnt = dev_ent[i];
  397.         rp->x.quit.psp_seg = psp_seg;
  398.         rp->stat = 0x0100;
  399.         break;
  400.  
  401.     default:
  402.         Device_call(dev,rp);
  403.         break;
  404.     }
  405.  
  406.     } else {
  407.     if ( Cache_off != FALSE ) {
  408.         Device_call(dev,rp);
  409.         return;
  410.     }
  411.  
  412.     switch(rp->cmds) {
  413.     case 1:        /* Media Check */
  414.         Device_call(dev,rp);
  415.         if ( (rp->stat & 0x8000) != 0 || rp->x.chk.now_sts <= 0 )
  416.         flush_dev(dev);
  417.         break;
  418.  
  419.     case 2:        /* Build BPB */
  420.         Device_call(dev,rp);
  421.         flush_dev(dev);
  422.         break;
  423.  
  424.     case 4:        /* Read */
  425.         sec = rp->x.rdwt.sect;
  426.         buf = rp->x.rdwt.buff;
  427.         i = rp->x.rdwt.count;
  428.  
  429.         while ( i-- > 0 ) {
  430.         if ( Cache_chk(dev,sec,buf) == FALSE )
  431.             goto CACHE_SET;
  432.         sec++;
  433.         buf += dp->SecLen;
  434.         }
  435.         rp->stat = 0x0100;
  436.         break;
  437.  
  438.     case 8:        /* Write */
  439.     case 9:        /* Write & Verify */
  440.     CACHE_SET:
  441.         sec = rp->x.rdwt.sect;
  442.         buf = rp->x.rdwt.buff;
  443.         i = rp->x.rdwt.count;
  444.  
  445.         Device_call(dev,rp);
  446.         if ( (rp->stat & 0x8000) != 0 ) {
  447.         flush_dev(dev);
  448.         break;
  449.         }
  450.  
  451.         while ( i-- > 0 ) {
  452.         Cache_set(dev,sec,buf);
  453.         sec++;
  454.         buf += dp->SecLen;
  455.         }
  456.         break;
  457.  
  458.     default:
  459.         Device_call(dev,rp);
  460.         if ( (rp->stat & 0x8000) != 0 )
  461.         flush_dev(dev);
  462.         break;
  463.     }
  464.     }
  465. }
  466. int    Dev_set(int dev,int unit)
  467. {
  468.     DPB far *dp;
  469.  
  470.     if ( dev == 0 )
  471.     dp = get_DPB(unit);
  472.     else {
  473.     dp = link_DPB();
  474.     while ( (long)dp != 0xFFFFFFFFL ) {
  475.         if ( dp->DrvNum == unit )
  476.         break;
  477.         dp = dp->NxtDPB;
  478.     }
  479.     }
  480.  
  481.     if ( (long)dp == 0xFFFFFFFFL )
  482.     return ERR;
  483.  
  484.     dpb_ptr[dev] = dp;
  485.     dev_ent[dev] = dpb_ptr[dev]->DevEnt;
  486.     dpb_ptr[dev]->DevEnt = dmy_dev + dev;
  487.  
  488.     dmy_dev[dev].next = dev_ent[dev]->next;
  489.     dmy_dev[dev].dev_sts = dev_ent[dev]->dev_sts;
  490.     dmy_dev[dev].res[0] = dev_ent[dev]->res[0];
  491.  
  492.     return FALSE;
  493. }
  494. int    setup(char *para)
  495. {
  496.     static int    i;
  497.     int    dev=0;
  498.     char   *p;
  499.     union {
  500.     char far *p;
  501.     short     s[2];
  502.     } sp;
  503.  
  504.     dmy_dev = init_dmy_dev();
  505.  
  506.     i = *(para++);
  507.     para[i] = '\0';
  508.     while ( *para != '\0' ) {
  509.     while ( *para != '\0' && *para <= ' ' ) para++;
  510.     if ( (*para >= 'a' && *para <= 'z') ||
  511.          (*para >= 'A' && *para <= 'Z') ) {
  512.         if ( Dev_set(dev++,(*para & 0xDF) - 'A') ) {
  513.             msg_disp("デバイスを確認できません\n\r$");
  514.             return 1;
  515.         }
  516.     }
  517.     while ( *para != '\0' && *para > ' ' ) para++;
  518.     }
  519.  
  520.     if ( dev == 0 ) {
  521.     msg_disp("use: CACHE <Buffer Device> <Cache Device....>\n\r$");
  522.     return 1;
  523.     }
  524.  
  525.     max_dev = dev;
  526.     SecLen = dpb_ptr[0]->SecLen;
  527.     SecAlc = dpb_ptr[0]->SecAlc + 1;
  528.     DatSec = dpb_ptr[0]->DatSec;
  529.     MaxCls = dpb_ptr[0]->MaxCls;
  530.     flush_tbl(MaxCls * SecAlc);
  531.     Cache_off = FALSE;
  532.  
  533.     if ( DOS_allocmem((SecLen+15U)/16,(unsigned *)&i) != FALSE ) {
  534.     msg_disp("セクタバッファメモリを確保できませんでした\n\r$");
  535.     goto ERROR;
  536.     }
  537.  
  538.     FP_OFF(tmp) = 0;
  539.     FP_SEG(tmp) = i;
  540.  
  541.     for ( i = 0 ; i < dpb_ptr[0]->FatSec ; i++ ) {
  542.     if ( Read_sub(dpb_ptr[0]->ResSec + i,tmp) == FALSE )
  543.         FAT_chk(i,tmp);
  544.     }
  545.  
  546.     DOS_memfree(FP_SEG(tmp));
  547.  
  548.     msg_disp("キャッシュが設定されました!!\n\r$");
  549.  
  550.     return 0;
  551.  
  552. ERROR:
  553.     for ( i = 0 ; i < max_dev ; i++ )
  554.     dpb_ptr[i]->DevEnt = dev_ent[i];
  555.  
  556.     return 1;
  557. }
  558.